package com.sto.common.importExcel.dubbo.service.impl;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.read.builder.ExcelReaderSheetBuilder;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.fastjson.JSON;
import com.sto.common.driverCost.entity.StoImportLog;
import com.sto.common.driverCost.service.IStoImportLogService;
import com.sto.common.error.ImportError;
import com.sto.common.importExcel.dto.base.BaseImportExcelDto;
import com.sto.common.importExcel.dto.request.ImportExcelRequest;
import com.sto.common.importExcel.dto.response.ImportExcelResponse;
import com.sto.common.importExcel.dubbo.service.AbstractImportExcelService;
import com.sto.common.importExcel.dubbo.service.BaseExcelServiceManage;
import com.sto.common.importExcel.factory.ExcelHandleFactory;
import com.sto.common.listener.AbsExcelListenerConsumer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.validation.Valid;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author ChenPeng
 * @since 2022-07-15 11:26
 */
@Slf4j
@Service
public class BaseExcelServiceManageImpl implements BaseExcelServiceManage {

    @Autowired
    IStoImportLogService stoImportLogService;


    @Override
    public ImportExcelResponse importExcel(@Valid ImportExcelRequest request) {
        //获取对应的服务实现类
        AbstractImportExcelService excelExecutor = ExcelHandleFactory.getImportExcelService(request.getExcelType());
        try {
            // 实现该方法即可
            BaseImportExcelDto importExcel = excelExecutor.importExcel(request);
            doRead(importExcel, request);
            excelExecutor.afterImportExcel(importExcel);
            recordImportLogInfo(request, importExcel);
            return importExcel.getExcelResponse();
        } catch (Exception e) {
            log.error("导入失败：msg{}", e.getMessage(), e);
            ImportError.BASE_ERROR.withMessage("导入失败：" + e.getMessage()).throwException();
            return null;
        }
    }

    /**
     * 读取文件，并执行业务逻辑
     *
     */
    private static void doRead(BaseImportExcelDto importExcel, ImportExcelRequest request) throws Exception {
        AbsExcelListenerConsumer excelConsumer = (AbsExcelListenerConsumer)importExcel.getExcelListenerConsumer();

        final String localPath = request.getLocalPath();

        if (StringUtils.isNotBlank(localPath)) {
            ExcelReaderSheetBuilder sheetBuilder = EasyExcelFactory
                    .read(localPath, importExcel.getClzDto(),  excelConsumer)
                    .sheet();
            Integer headRowNumber = importExcel.getHeadRowNumber();
            if (headRowNumber != null) {
                sheetBuilder.headRowNumber(headRowNumber);
            }
            sheetBuilder.doRead();
            return;
        }

        try (InputStream inputStream = new URL(request.getExcelUrl()).openStream()) {
            ExcelReaderSheetBuilder sheetBuilder = EasyExcelFactory
                    .read(inputStream, importExcel.getClzDto(), excelConsumer)
                    .sheet();
            Integer headRowNumber = importExcel.getHeadRowNumber();
            if (headRowNumber != null) {
                sheetBuilder.headRowNumber(headRowNumber);
            }
            sheetBuilder.doRead();
        } catch (IOException e) {
            log.error("文件打开失败");
        }
    }

    /**
     * 错误日志导出
     */
    private void recordImportLogInfo(ImportExcelRequest importExcelRequest, BaseImportExcelDto importExcel) {
        ImportExcelResponse response = importExcel.getExcelResponse();
        try {
            log.warn("导入成功：request{} before result:{},afterImportExcel", JSON.toJSONString(importExcelRequest),
                    JSON.toJSONString(response), JSON.toJSONString(response));
            StoImportLog log = new StoImportLog();
            log.setType(ExcelHandleFactory.IMPORT_STRATEGY_TYPE
                    .getOrDefault(importExcelRequest.getExcelType().toLowerCase(), StringUtils.EMPTY));
            log.setTotalCount(Optional.ofNullable(response.getTotalCount()).map(AtomicInteger::longValue).orElse(0L));
            log.setSuccessCount(Optional.ofNullable(response.getSuccessCount()).map(AtomicInteger::longValue)
                    .orElse(0L));
            log.setFailCount(Optional.ofNullable(response.getErrorCount()).map(AtomicInteger::longValue)
                    .orElse(0L));
            log.setUrl(Optional.ofNullable(response.getExcelUrl()).orElse(StringUtils.EMPTY));
            stoImportLogService.save(log);
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }
}
